﻿/*
 * @Autor: PK
 * @Date: 2022/01/15 09:41:SS
 */

using System;
using System.Collections.Generic;
using System.Linq;
using NLog;
using O2DESNet;
using ShkSimulation.core.dao.input.resource;
using ShkSimulation.core.exceptions;

namespace ShkSimulation.core.template.customer {

	public abstract class DemandManager: Sandbox {
		
		protected static readonly Logger logger = LogManager.GetLogger(nameof(DemandManager));
		protected Dictionary<string, CustomerTemplate> buffer;
		
		protected Resource DemandData { get; set; }
		protected internal List<CustomerTemplate> Templates { get; internal set; }
		public IReadOnlyList<CustomerTemplate> CustomerTemplate { get { return Templates?.AsReadOnly(); } }
		public NetworkInputData NetworkInputData { get; set; }
		
		protected void ContinusCreateCustomer(CustomerTemplate template) {
			DateTime next = template.GetCreateTimeAndPassNext(ClockTime);
			Customer customer = template.CreateCustomer();
			Schedule(() => {
				customer.EnterNextAgency();
				ContinusCreateCustomer(template);
			}, next);
		}
		
		public CustomerTemplate GetCustomerTemplateByAgenciesIds(int origin, int destination) {
			string key = $"{origin}-{destination}";
			if (buffer.ContainsKey(key)) {
				return buffer[key];
			}
			List<CustomerTemplate> result = new List<CustomerTemplate>();
			foreach (var customerTemplate in Templates) {
				List<int> agencies = customerTemplate.GetCustomerAgencies()
					.Select(each => each.UniqueId).ToList();
				if (agencies.Count < 2) {
					continue;
				}
				if (agencies.First() == origin && agencies.Last() == destination) {
					result.Add(customerTemplate);
				}
			}
			if (result.Count != 1) {
				throw new ErrorParamException($"GetCustomerTemplateByAgenciesIds get zero or more than one " +
				                              $"template:{result.Count}, origin:{origin}, destination:{destination}");
			}
			CustomerTemplate template = result.First();
			buffer.Add(key, template);
			return template;
		}
		
		public abstract List<CustomerTemplate> InitializeCustomerTemplate(NetworkInputData environment);

		public virtual void Start() {
			foreach (var template in Templates) {
				ContinusCreateCustomer(template);
			}
		}

		public abstract DemandManager Clone();

		public static TimeSpan DemandToTimeSpanWithTimeUnit(double demand, string timeUnit) {
			if (demand < 0) {
				throw new ErrorParamException("需求不能小于0");
			}
			if (demand == 0) {
				return TimeSpan.MaxValue;
			}
			demand = 1.0 / demand;
			switch (timeUnit) {
				case "M":
				case "分":
				case "分钟":
				case "m":
				case "Minute":
				case "minute":
					return TimeSpan.FromMinutes(demand);
				case "H":
				case "h":
				case "是":
				case "小时":
				case "Hour":
				case "hour":
					return TimeSpan.FromHours(demand);
				case "Day":
				case "day":
				case "天":
				case "日":
				case "D":
				case "d":
					return TimeSpan.FromDays(demand);
				case "S":
				case "s":
				case "秒":
				case "Second":
				case "second":
					return TimeSpan.FromSeconds(demand);
				default:
					return TimeSpan.FromHours(demand);
			}
		}


	}

}